package com.yilin.tms.order.controller;

import cn.hutool.json.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.reflect.TypeToken;
import com.yilin.commons.exception.BusinessException;
import com.yilin.commons.util.ArrayUtil;
import com.yilin.commons.util.GpsMapUtil;
import com.yilin.commons.util.JsonUtil;
import com.yilin.commons.util.StringUtil;
import com.yilin.tms.core.application.PageData;
import com.yilin.tms.core.application.ReturnData;
import com.yilin.tms.core.commons.annotation.*;
import com.yilin.tms.core.commons.utils.ParamUtil;
import com.yilin.tms.core.commons.utils.UserUtil;
import com.yilin.tms.core.commons.base.BaseController;
import com.yilin.tms.core.entity.order.goods.GoodsOrder;
import com.yilin.tms.core.entity.order.goods.ordinary.GoodsNote;
import com.yilin.tms.core.entity.order.goods.ordinary.GoodsOrdinary;
import com.yilin.tms.core.entity.order.party.OrderAutLog;
import com.yilin.tms.core.entity.order.party.ReceiptChangeRecord;
import com.yilin.tms.core.entity.order.payment.OrderPaymentCost;
import com.yilin.tms.core.entity.order.rob.RobOrder;
import com.yilin.tms.core.entity.order.transit.TransitOrderNote;
import com.yilin.tms.core.entity.order.transit.TransitOrderNoteDetail;
import com.yilin.tms.core.entity.order.transit.TransitOrder;
import com.yilin.tms.core.entity.order.transit.TransitOrderVehicleRecord;
import com.yilin.tms.core.entity.system.param.TruckType;
import com.yilin.tms.core.entity.truck.TruckVehicle;
import com.yilin.tms.core.entity.user.UserType;
import com.yilin.tms.core.entity.user.account.Account;
import com.yilin.tms.core.entity.user.organize.MemberType;
import com.yilin.tms.core.entity.user.organize.Organize;
import com.yilin.tms.order.service.order.IRobService;
import com.yilin.tms.order.service.order.ITransitService;
import com.yilin.tms.order.service.owner.ITransitOwnerService;
import com.yilin.tms.order.service.party.IOrderAutLogService;
import com.yilin.tms.order.service.payment.IOrderPaymentCostService;
import com.yilin.tms.core.remote.IGpsRemote;
import com.yilin.tms.core.remote.IUserRemote;
import com.yilin.tms.core.remote.IVehicleRemote;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.persistence.Column;
import java.util.*;

/**
 * 运单控制器
 *
 * @author zhangjinyuan
 * @date 2022/10/31
 */
@RestController
@RequestMapping("/order/transit/")
public class TransitController extends BaseController {

    @Resource
    private ITransitService transitService;
    @Resource
    private IRobService robService;
    @Resource
    private IOrderAutLogService orderAutLogService;
    @Resource
    private ITransitOwnerService transitOwnerService;
    @Resource
    private IOrderPaymentCostService orderPaymentCostService;

    @Resource
    private IUserRemote userRemote;
    @Resource
    private IVehicleRemote vehicleRemote;
    @Resource
    private IGpsRemote gpsRemote;

    /**
     * 保存普通运单
     */
    @PostMapping(value = "saveOrdinary")
    public ReturnData<PageData<TransitOrder>> saveOrdinary(String goodsOrdinaryJson, String goodsNoteJson) {
        GoodsOrdinary goodsOrdinary = JsonUtil.jsonToObject(goodsOrdinaryJson, new TypeToken<GoodsOrdinary>() {
        });
        ParamUtil.isNull(goodsOrdinary, "货物实体转换失败");
        ParamUtil.isNull(goodsOrdinary.getTrackId(), "货物实体转换失败");
        ParamUtil.isNull(goodsOrdinary.getConsignorName(), "发货人不能为空");
        ParamUtil.isNull(goodsOrdinary.getConsignorPhone(), "发货人手机为空");
        ParamUtil.isNull(goodsOrdinary.getConsignorAddress(), "发货人地址为空");
        ParamUtil.isNull(goodsOrdinary.getConsigneeName(), "收货人不能为空");
        ParamUtil.isNull(goodsOrdinary.getConsigneePhone(), "收货人手机为空");
        ParamUtil.isNull(goodsOrdinary.getConsigneeAddress(), "收货人地址为空");
        TruckVehicle truckVehicle = ParamUtil.isSuccess(vehicleRemote.getVehicleById(goodsOrdinary.getTrackId()));
        ParamUtil.isNull(truckVehicle, "获取车辆信息失败");
        if (truckVehicle.getTruckStatus() != TruckVehicle.TruckStatus.unused) {
            return jsonView(false, "车辆状态不在空闲中");
        }
        if (truckVehicle.getTruckTypeTowingType() == TruckType.TowingType.trailer) {
            ParamUtil.isNull(truckVehicle.getTractorNo(), "请绑定挂车！");
            TruckVehicle truckVehicleTract = ParamUtil.isSuccess(vehicleRemote.getTruckByTruckNo(truckVehicle.getTractorNo()));
            ParamUtil.isNull(truckVehicleTract, "获取挂车信息失败");
            if (truckVehicleTract.getTruckStatus() != TruckVehicle.TruckStatus.unused) {
                return jsonView(false, "挂车状态不在空闲中");
            }
        }
        List<GoodsNote> goodsNoteList = JsonUtil.jsonToObject(goodsNoteJson, new TypeToken<List<GoodsNote>>() {
        });
        transitService.saveOrdinary(getLoginUser(), goodsOrdinary, goodsNoteList, truckVehicle);
        return jsonView(SUCCESS_CODE, "保存成功" );
    }


    /**
     * 获取运单分页
     */
    @PostMapping(value = "getTransitOrderPage")
    @NotNull({"page", "limit"})
    public ReturnData<PageData<TransitOrder>> getTransitOrderPage(TransitOrder query, @Explain("页码") Integer page, @Explain("条数") Integer limit) {
        PageData<TransitOrder> pageData = transitService.getTransitOrderPage(getLoginUser(), query, page, limit);
        return jsonView(SUCCESS_CODE, "获取运单列表成功", pageData);
    }

    /**
     * 获取平台未生成或生产失败的数据
     */
    @PostMapping(value = "getErrorTmsTransitOrder")
    public ReturnData<List<TransitOrder>> getErrorTmsTransitOrder(Integer transitTruckTowingType) {
        List<TransitOrder> transitOrderList = transitService.getErrorTmsTransitOrder(transitTruckTowingType);
        return jsonView(SUCCESS_CODE, "获取运单列表成功", transitOrderList);
    }

    /**
     * 获取运单详情
     */
    @PostMapping(value = "getTransitOrderDetail")
    public ReturnData<TransitOrder> getTransitOrderDetail(String transitOrderId) {
        TransitOrder transitOrder = transitService.getTransitOrderDetail(getLoginUser(), transitOrderId);
        return jsonView(SUCCESS_CODE, "获取运单详情成功", transitOrder);
    }

    /**
     * IDS批量获取订单信息
     */
    @PostMapping(value = "getTransitOrderListByIds")
    @NotNull({"transitOrderIds"})
    public ReturnData<Object> getTransitOrderListByIds(@Explain("运单ID组") String[] transitOrderIds) {
        List<TransitOrder> transitOrderList = transitService.getTransitOrderListByIds(transitOrderIds);
        return jsonView(SUCCESS_CODE, "查询成功", transitOrderList);
    }

    /**
     * 运单号批量获取订单信息
     */
    @PostMapping(value = "getTransitOrderListByNos")
    @NotNull({"transportNos"})
    public ReturnData<Object> getTransitOrderListByNos(@Explain("运单号组") String[] transportNos) {
        List<TransitOrder> transitOrderList = transitService.getTransitOrderListByNos(transportNos);
        return jsonView(SUCCESS_CODE, "查询成功", transitOrderList);
    }

    /**
     * 获取运单货物节点列表
     */
    @PostMapping(value = "getTransitOrderNoteList")
    @NotNull("transitOrderId")
    @NoLoginSecurity//允许免登录获取，但是必须注入安全头
    public ReturnData<List<TransitOrderNote>> getTransitOrderNoteList(@Explain("运单ID") String transitOrderId, TransitOrderNote.NoteStatus noteStatus, Boolean containDetail) {
        if (containDetail == null) containDetail = true;
        List<TransitOrderNote> transitOrderNoteList = transitService.getTransitOrderNoteList(transitOrderId, noteStatus, containDetail);
        return jsonView(SUCCESS_CODE, "获取货物节点列表成功", transitOrderNoteList);
    }

    /**
     * 获取运单节点
     */
    @PostMapping(value = "getTransitOrderNoteById")
    @NotNull("transitOrderNoteId")
    @SkipLoginVerify
    public ReturnData<TransitOrderNote> getTransitOrderNoteById(@Explain("节点ID") String transitOrderNoteId) {
        TransitOrderNote transitOrderNote = transitService.getTransitOrderNoteById(transitOrderNoteId);
        return jsonView(SUCCESS_CODE, "获取节点成功", transitOrderNote);
    }


    /**
     * 获取运单节点货物列表
     */
    @PostMapping(value = "getTransitNoteDetailList")
    @NotNull("transitOrderNoteId")
    @SkipLoginVerify
    public ReturnData<List<TransitOrderNoteDetail>> getTransitNoteDetailList(@Explain("节点ID") String transitOrderNoteId) {
        List<TransitOrderNoteDetail> transitOrderNoteDetailList = transitService.getTransitOrderNoteDetailList(transitOrderNoteId);
        return jsonView(SUCCESS_CODE, "获取节点货物列表成功", transitOrderNoteDetailList);
    }

    /**
     * 获取运单所有节点货物列表
     */
    @PostMapping(value = "getAllTransitDetailList")
    @NotNull("transitOrderId")
    @SkipLoginVerify
    public ReturnData<List<TransitOrderNoteDetail>> getAllTransitDetailList(@Explain("运单ID") String transitOrderId) {
        List<TransitOrderNoteDetail> transitOrderNoteDetailList = transitService.getAllTransitOrderDetailList(transitOrderId);
        return jsonView(SUCCESS_CODE, "获取节点货物列表成功", transitOrderNoteDetailList);
    }

    /**
     * 获取司机正在进行中的订单
     */
    @PostMapping(value = "getRunTransitOrderListByDriver")
    @UserTarget({UserType.truckerUser})
    public ReturnData<List<TransitOrder>> getRunTransitOrderListByDriver(String driverUserId) {
        if (StringUtil.isEmpty(driverUserId)) driverUserId = getLoginUser().getId();
        List<TransitOrder> viewList = transitService.getRunTransitOrderListByDriver(driverUserId);
        return jsonView(SUCCESS_CODE, "获取成功", viewList);
    }

    /**
     * 根据ID获取运单
     */
    @PostMapping(value = "getTransitOrderById")
    @NotNull("transitOrderId")
    public ReturnData<TransitOrder> getTransitOrderById(@Explain("运单ID") String transitOrderId) {
        TransitOrder transitOrder = transitService.getById(transitOrderId);
        return jsonView(true, "获取运单详情成功", transitOrder);
    }

    /**
     * 根据运单号获取运单
     */
    @PostMapping(value = "getTransitOrderByNo")
    @NotNull("transportNo")
    @NoLoginSecurity
    @SkipLoginVerify
    public ReturnData<TransitOrder> getTransitOrderByNo(@Explain("运单号") String transportNo) {
        TransitOrder transitOrder = transitService.getTransitOrderByNo(transportNo);
        return jsonView(true, "获取运单详情成功", transitOrder);
    }

    /**
     * 获取运单分页 隐藏敏感信息
     */
    @PostMapping(value = "getPublicTransitOrderPage")
    @NotNull({"page", "limit"})
    public ReturnData<PageData<TransitOrder>> getPublicTransitOrderPage(TransitOrder query, @Explain("页码") Integer page, @Explain("条数") Integer limit) {
        PageData<TransitOrder> pageData = transitService.getPublicTransitOrderPage(query, page, limit);
        return jsonView(SUCCESS_CODE, "获取运单列表成功", pageData);
    }

    /**
     * 获取地图货源节点导航列表
     */
    @PostMapping(value = "getMapTransitNoteData")
    @NotNull("transitOrderId")
    public ReturnData<Map<String, Object>> getMapTransitNoteData(@Explain("运单ID") String transitOrderId, @Explain("司机坐标") String truckLngLat) {
        TransitOrder transitOrder = transitService.getById(transitOrderId);
        Map<String, Object> mapTransitNoteData = new HashMap<>();
        if (transitOrder.getTransitStatus() == TransitOrder.TransitStatus.waitingLoading) {
            mapTransitNoteData = transitService.getMapNoteDataListByLoading(transitOrderId, truckLngLat);
        } else if (transitOrder.getTransitStatus() == TransitOrder.TransitStatus.waitingArrive) {
            mapTransitNoteData = transitService.getMapNoteDataListByReceipt(transitOrderId);
        }
        return jsonView(SUCCESS_CODE, "获取待装货货物节点列表成功", mapTransitNoteData);
    }

    /**
     * 确认装货
     */
    @PostMapping(value = "confirmLoading")
    @NotNull({"id", "transitOrderNoteList"})
    @UserTarget({UserType.truckerUser})
    public ReturnData<Object> confirmLoading(TransitOrder transitOrder) {
        TransitOrder localTransitOrder = transitService.getById(transitOrder.getId());
        ParamUtil.notEquals("运单锁定中", localTransitOrder.getOperateStatus(), TransitOrder.OperateStatus.none);
        ParamUtil.equals("运单锁定中,请等待处理完成", localTransitOrder.getLockingStatus(), TransitOrder.LockingStatus.locking);
        ParamUtil.notEquals("你无权操作", localTransitOrder.getTransitTruckUserId(), getLoginUser().getId());
        ParamUtil.notEquals("运单不在装货状态，不能装货", localTransitOrder.getTransitStatus(), TransitOrder.TransitStatus.waitingLoading);
        List<TransitOrderNote> transitOrderNoteList = transitOrder.getTransitOrderNoteList();
        for (TransitOrderNote transitOrderNote : transitOrderNoteList) {
            List<TransitOrderNoteDetail> transitOrderNoteDetailList = transitOrderNote.getTransitOrderNoteDetailList();
            if (transitOrderNoteDetailList == null || transitOrderNoteDetailList.size() == 0)
                throw new BusinessException("请提供装货信息");
            if (transitOrderNote.getId() == null) throw new BusinessException("请无效装货节点");
            if (localTransitOrder.getNeedUploadShipping())
                ParamUtil.isNull(transitOrderNote.getNoteLoadingImg(), "运单需装货拍照，请至少提供一张装货图片");
            if (transitOrderNote.getNoteLoadingImg() != null && transitOrderNote.getNoteLoadingImg().split(",").length > 6)
                throw new BusinessException("最多能上传6张图片");
            for (TransitOrderNoteDetail transitOrderNoteDetail : transitOrderNote.getTransitOrderNoteDetailList()) {
                ParamUtil.isNull(transitOrderNoteDetail.getId(), "无效货物标识");
                if (transitOrderNoteDetail.getLoadingMeasure() == null || transitOrderNoteDetail.getLoadingMeasure() <= 0) {
                    throw new BusinessException("装货输入不能等于或低于0");
                }
            }
        }
        //transitOrder -> localTransitOrder
        transitService.confirmLoading(getLoginUser(), localTransitOrder, transitOrderNoteList);
        return jsonView(SUCCESS_CODE, "确认装货成功", null);
    }

    /**
     * 确认发货+签订合同
     */
    @PostMapping(value = "confirmDelivery")
    @NotNull({"id"})
    @UserTarget({UserType.shipperUser})
    public ReturnData<Object> confirmDelivery(TransitOrder transitOrder) {
        if (transitOrder.getTransitOrderNoteList() == null) throw new BusinessException("无效发货节点");
        for (TransitOrderNote transitOrderNote : transitOrder.getTransitOrderNoteList()) {
            ParamUtil.isNull(transitOrderNote.getId(), "无效节点");
            if (transitOrderNote.getTransitOrderNoteDetailList() == null) throw new BusinessException("无效货物信息");
            for (TransitOrderNoteDetail transitOrderNoteDetail : transitOrderNote.getTransitOrderNoteDetailList()) {
                if (transitOrderNoteDetail.getDeliverMeasure() == null || transitOrderNoteDetail.getDeliverMeasure() <= 0) {
                    throw new BusinessException("发货输入不能等于或低于0");
                }
            }
        }
        TransitOrder localTransitOrder = transitService.getById(transitOrder.getId());
        ParamUtil.isNull(localTransitOrder, "无效运单");
        ParamUtil.notEquals("运单锁定中", localTransitOrder.getOperateStatus(), TransitOrder.OperateStatus.none);
        ParamUtil.equals("运单锁定中,请等待处理完成", localTransitOrder.getLockingStatus(), TransitOrder.LockingStatus.locking);
        ParamUtil.notEquals("运单未在发货状态，不能发货", localTransitOrder.getTransitStatus(), TransitOrder.TransitStatus.waitingDelivery);
        ParamUtil.notEquals("你无权操作此运单", localTransitOrder.getShipperAccountId(), getLoginUser().getId());
        Organize organize = ParamUtil.isSuccess(userRemote.getOrganizeById(localTransitOrder.getShipperOrganizeId()));
        ParamUtil.isNull(organize.getSignatureImg(), "电子签章/签名未完成");
        //transitOrder -> localTransitOrder
        localTransitOrder.setTransitOrderNoteList(transitOrder.getTransitOrderNoteList());
        transitService.confirmDelivery(getLoginUser(), localTransitOrder, false);
        return jsonView(SUCCESS_CODE, "确认发货成功");
    }

    /**
     * 批量发货
     */
    @PostMapping(value = "multiConfirmDelivery")
    @NotNull({"transitOrderIds"})
    @UserTarget({UserType.shipperUser})
    @SafeVerify
    public ReturnData<Object> multiConfirmDelivery(@Explain("运单ID数组") String[] transitOrderIds) {
        int success = transitService.multiConfirmDelivery(getLoginUser(), transitOrderIds);
        return jsonView(true, "发货成功：" + success + "条，失败：" + (transitOrderIds.length - success) + "条");
    }

    /**
     * 确认运输+签订合同
     */
    @PostMapping(value = "confirmTransit")
    @NotNull({"planningConsignorNoteId", "planningConsigneeNoteId", "sortConsigneeNoteIds"})
    @UserTarget({UserType.truckerUser})
    public ReturnData<Object> confirmTransit(TransitOrder transitOrder) {
        if (transitOrder.getAdditionalCost() != null && StringUtil.isEmpty(transitOrder.getAdditionalDetails())) {
            return jsonView(false, "附加费原因不能为空");
        }
        TransitOrder localTransitOrder = transitService.getById(transitOrder.getId());
        ParamUtil.isNull(localTransitOrder, "未知运单");
        ParamUtil.notEquals("运单锁定中", localTransitOrder.getOperateStatus(), TransitOrder.OperateStatus.none);
        ParamUtil.equals("运单锁定中,请等待处理完成", localTransitOrder.getLockingStatus(), TransitOrder.LockingStatus.locking);
        ParamUtil.notEquals("运单未在等待运输状态，不能运输", localTransitOrder.getTransitStatus(), TransitOrder.TransitStatus.waitingTransit);
        ParamUtil.notEquals("你无权操作此运单", localTransitOrder.getTransitTruckUserId(), getLoginUser().getId());
        if (localTransitOrder.getTransitTruckTowingType() == TruckType.TowingType.tractor) {
            if (transitOrder.getTransitTrailerId() == null && localTransitOrder.getTransitTrailerId() == null) {
                return jsonView(false, "请添加挂车车厢");
            }
            TruckVehicle trailer = ParamUtil.isSuccess(vehicleRemote.getVehicleById(transitOrder.getTransitTrailerId()));
            if (trailer.getTruckTypeTowingType() != TruckType.TowingType.trailer) {
                return jsonView(false, "请选择正确的挂车车厢");
            }
            localTransitOrder.setTransitTrailerId(transitOrder.getTransitTrailerId());
            localTransitOrder.setTransitTrailerNo(trailer.getTrackNo());
            localTransitOrder.setTransitTrailerWeight(trailer.getVehicleWeight());
            localTransitOrder.setTransitTrailerLoadingWeight(trailer.getLoadingWeight());
        }
        //检查支付状态
        RobOrder localRobOrder = robService.getById(localTransitOrder.getRobOrderId());
        OrderPaymentCost paymentCost = orderPaymentCostService.generateDeliveryOrderPayment(localTransitOrder, localRobOrder);
        List<OrderPaymentCost.PayStatus> payStatuses = ArrayUtil.initList(OrderPaymentCost.PayStatus.none, OrderPaymentCost.PayStatus.complete);
        if (!payStatuses.contains(paymentCost.getPayStatus()))
            return jsonErrView("请先等待货主支付发货运费，运输完成前，运费交由平台托管！");
        // transitOrder => localTransitOrder
        if (localTransitOrder.getTransitTrailerId() != null) {
            TruckVehicle truckVehicle = ParamUtil.isSuccess(vehicleRemote.getVehicleById(localTransitOrder.getTransitTrailerId()));
            if (truckVehicle.getTruckStatus() != TruckVehicle.TruckStatus.unused)
                return jsonErrView("您提交的挂车已在忙碌中！");
            localTransitOrder.setTransitTrailerNo(truckVehicle.getTrackNo());
            localTransitOrder.setTransitTrailerWeight(truckVehicle.getVehicleWeight());
            localTransitOrder.setTransitTrailerLoadingWeight(truckVehicle.getLoadingWeight());
        }
        //-->GPS猎鹰数据
        localTransitOrder.setGeoServiceId(getLoginUser().getGeoServiceId());
        localTransitOrder.setGeoTerminalId(getLoginUser().getGeoTerminalId());
        localTransitOrder.setGeoTrackTraceId(transitOrder.getGeoTrackTraceId());
        //-->省级运管数据
        localTransitOrder.setPlanningConsignorNoteId(transitOrder.getPlanningConsignorNoteId());
        localTransitOrder.setPlanningConsignorCoordinate(transitOrder.getPlanningConsignorCoordinate());
        localTransitOrder.setPlanningConsignorAddress(transitOrder.getPlanningConsignorAddress());
        localTransitOrder.setPlanningConsignorAdCode(transitOrder.getPlanningConsignorAdCode());
        localTransitOrder.setPlanningConsigneeNoteId(transitOrder.getPlanningConsigneeNoteId());
        localTransitOrder.setPlanningConsigneeCoordinate(transitOrder.getPlanningConsigneeCoordinate());
        localTransitOrder.setPlanningConsigneeAddress(transitOrder.getPlanningConsigneeAddress());
        localTransitOrder.setPlanningConsigneeAdCode(transitOrder.getPlanningConsigneeAdCode());
        localTransitOrder.setSortConsigneeNoteIds(transitOrder.getSortConsigneeNoteIds());
        //-->附加费数据
        String traceId = transitService.confirmTransit(getLoginUser(), localTransitOrder);
        return jsonView(SUCCESS_CODE, "确认运输成功", traceId);
    }

    /**
     * 申请暂停运单
     */
    @PostMapping(value = "applyPausing")
    @NotNull({"transitOrderId", "transitPauseCoordinate"})
    @UserTarget({UserType.platformUser, UserType.truckerUser})
    public ReturnData<Object> applyPausing(@Explain("运单ID") String transitOrderId, @Explain("暂停坐标") String transitPauseCoordinate) {
        TransitOrder localTransitOrder = transitService.getById(transitOrderId);
        ParamUtil.isNull(localTransitOrder, "未知的运单");
        ParamUtil.isNull(transitPauseCoordinate, "暂停位置不能为空");
        ParamUtil.notEquals("仅限运单司机操作", localTransitOrder.getTransitTruckUserId(), getLoginUser().getId());
        if (localTransitOrder.getTransitStatus() != TransitOrder.TransitStatus.waitingLoading
                && localTransitOrder.getTransitStatus() != TransitOrder.TransitStatus.waitingArrive)
            return jsonErrView("运单不在运输中！");
        if (localTransitOrder.getLockingStatus() == TransitOrder.LockingStatus.locking)
            return jsonErrView("运单锁定中！");
        if (localTransitOrder.getOperateStatus() == TransitOrder.OperateStatus.pausing)
            return jsonErrView("运单已暂停！");
//        Map<String, Object> map = ParamUtil.isSuccess(gpsRemote.getAddressInfoByPoint(localTransitOrder.getPlatId(), transitPauseCoordinate));
//        localTransitOrder.setTransitPauseCoordinate(transitPauseCoordinate);
//        localTransitOrder.setTransitPauseAddress((String) map.get("address"));
//        localTransitOrder.setTransitPauseAdCode((String) map.get("adcode"));
        transitService.applyPausing(getLoginUser(), localTransitOrder);
        return jsonView(true, "运单暂停成功");
    }

    /**
     * 申请恢复运单
     */
    @PostMapping(value = "applyRecovery")
    @NotNull({"transitOrderId"})
    @UserTarget({UserType.platformUser, UserType.truckerUser})
    public ReturnData<Object> applyRecovery(@Explain("运单ID") String transitOrderId, @Explain("恢复坐标") String transitRestoreCoordinate) {
        TransitOrder localTransitOrder = transitService.getById(transitOrderId);
        ParamUtil.isNull(localTransitOrder, "无效运单");
        ParamUtil.isNull(transitRestoreCoordinate, "恢复位置不能为空");
        ParamUtil.notEquals("仅限运单司机操作", localTransitOrder.getTransitTruckUserId(), getLoginUser().getId());
        if (localTransitOrder.getTransitStatus() != TransitOrder.TransitStatus.waitingLoading
                && localTransitOrder.getTransitStatus() != TransitOrder.TransitStatus.waitingArrive)
            return jsonErrView("运单不在运输中！");
        if (localTransitOrder.getLockingStatus() == TransitOrder.LockingStatus.locking)
            return jsonErrView("运单锁定中！");
        if (localTransitOrder.getOperateStatus() != TransitOrder.OperateStatus.pausing)
            return jsonErrView("运单无需恢复！");
        double distance = GpsMapUtil.getDistance(transitRestoreCoordinate, localTransitOrder.getTransitPauseCoordinate());
        MemberType memberType = ParamUtil.isSuccess(userRemote.getMyMemberTypeByOrganizeId(getLoginUser().getOrganizeId()));
        if (distance > memberType.getElectronicFenceRange())
            return jsonErrView("你在运单暂停期间离开暂停位置，请在暂停位置附近重新恢复运单！");
        transitService.applyRecovery(getLoginUser(), localTransitOrder);
        return jsonView(true, "运单暂停成功");
    }

    /**
     * 运单中途换车/换人
     */
    @PostMapping(value = "changeTruckOrUser")
    @NotNull({"id"})
    @UserTarget({UserType.truckerUser})
    public ReturnData<Object> changeTruckOrUser(@Explain("运单ID") String transitOrderId, @Explain("车辆ID") String vehicleId, @Explain("挂车ID") String trailerId) {
        TransitOrder localTransitOrder = transitService.getById(transitOrderId);
        ParamUtil.isNull(localTransitOrder, "未知的运单");
        ParamUtil.notEquals("您无权操作该运单", getLoginUser().getId(), localTransitOrder.getRobAccountId());
        if (localTransitOrder.getOperateStatus() != TransitOrder.OperateStatus.pausing)
            return jsonErrView("请先让司机暂停运单，再完成换车/换人操作！");
        TruckVehicle truckVehicle = ParamUtil.isSuccess(vehicleRemote.getVehicleById(vehicleId));
        if (truckVehicle.getTruckStatus() == TruckVehicle.TruckStatus.using)
            return jsonErrView("目标车辆状态忙碌，请选择其他车辆");
        if (truckVehicle.getTruckUserId() == null) return jsonErrView("目标车辆未綁定驾驶员");
        TruckVehicle trailer = trailerId == null ? null : ParamUtil.isSuccess(vehicleRemote.getVehicleById(trailerId));
        if (trailer != null && trailer.getTruckStatus() == TruckVehicle.TruckStatus.using)
            return jsonErrView("目标挂车正在使用，请使用其他挂车");
        transitService.changeTruckOrUser(getLoginUser(), localTransitOrder, truckVehicle, trailer);
        return jsonView(true, "更换成功");
    }

    /**
     * 节点收货变更记录
     */
    @PostMapping(value = "getChangeNoteReceiptRecordList")
    @UserTarget({UserType.shipperUser, UserType.truckerUser})
    public ReturnData<Object> getChangeNoteReceiptRecordList(@Explain("运单ID") String transitOrderId) {
        List<ReceiptChangeRecord> noteReceiptRecordList = transitService.getChangeNoteReceiptRecordList(transitOrderId);
        return jsonView(true, "更换成功", noteReceiptRecordList);
    }

    /**
     * 临时申请变更节点收货地址
     */
    @PostMapping(value = "applyChangeNoteReceiptAddress")
    @NotNull({"transitOrderId", "transitOrderNoteId"})
    @UserTarget({UserType.shipperUser})
    public ReturnData<Object> applyChangeNoteReceiptAddress(ReceiptChangeRecord changeRecord) {
        TransitOrderNote transitOrderNote = transitService.getTransitOrderNoteById(changeRecord.getTransitOrderNoteId());
        if (StringUtil.isEmpty(changeRecord.getConsigneeAdCode()))
            changeRecord.setConsigneeAdCode(transitOrderNote.getConsigneeAdCode());
        if (StringUtil.isEmpty(changeRecord.getConsigneeArea()))
            changeRecord.setConsigneeArea(transitOrderNote.getConsigneeArea());
        if (StringUtil.isEmpty(changeRecord.getConsigneeCoordinate()))
            changeRecord.setConsigneeCoordinate(transitOrderNote.getConsigneeCoordinate());
        if (StringUtil.isEmpty(changeRecord.getConsigneeName()))
            changeRecord.setConsigneeName(transitOrderNote.getConsigneeName());
        if (StringUtil.isEmpty(changeRecord.getConsigneePhone()))
            changeRecord.setConsigneePhone(transitOrderNote.getConsigneePhone());
        transitService.applyChangeNoteReceiptAddress(getLoginUser(), changeRecord);
        return jsonView(true, "申请成功");
    }

    /**
     * reply申请变更节点收货地址
     */
    @PostMapping(value = "replyChangeNoteReceiptAddress")
    @NotNull({"transitOrderId", "transitOrderNoteId"})
    @UserTarget({UserType.truckerUser})
    public ReturnData<Object> replyChangeNoteReceiptAddress(String changeRecordId, ReceiptChangeRecord.ChangeState changeState) {
        if (changeState == ReceiptChangeRecord.ChangeState.agreed) {
            transitService.agreedChangeNoteReceiptAddress(getLoginUser(), changeRecordId);
        } else if (changeState == ReceiptChangeRecord.ChangeState.refused) {
            transitService.refuseChangeNoteReceiptAddress(getLoginUser(), changeRecordId);
        }
        return jsonView(true, "回复成功");
    }

    /**
     * 确认送达 + 生成电子回单
     * transitOrder中强制结束坐标不为null时为运单强制送达
     */
    @PostMapping(value = "confirmArrive")
    @NotNull({"id", "transitOrderNoteList"})
    @UserTarget({UserType.truckerUser})
    public ReturnData<Object> confirmArrive(TransitOrder transitOrder) {
        TransitOrder localTransitOrder = transitService.getById(transitOrder.getId());
        ParamUtil.notEquals("运单锁定中", localTransitOrder.getOperateStatus(), TransitOrder.OperateStatus.none);
        ParamUtil.equals("运单锁定中,请等待处理完成", localTransitOrder.getLockingStatus(), TransitOrder.LockingStatus.locking);
        ParamUtil.notEquals("你无权操作", localTransitOrder.getTransitTruckUserId(), getLoginUser().getId());
        ParamUtil.notEquals("运单不在运输状态，不能送达", localTransitOrder.getTransitStatus(), TransitOrder.TransitStatus.waitingArrive);
        List<TransitOrderNote> transitOrderNoteList = transitOrder.getTransitOrderNoteList();
        for (TransitOrderNote transitOrderNote : transitOrderNoteList) {
            List<TransitOrderNoteDetail> transitOrderNoteDetailList = transitOrderNote.getTransitOrderNoteDetailList();
            if (transitOrderNoteDetailList == null || transitOrderNoteDetailList.size() == 0)
                throw new BusinessException("请提供收货信息");
            if (transitOrderNote.getId() == null) throw new BusinessException("请无效收货节点");
            ParamUtil.isNull(localTransitOrder, "没有找到运单");
            if (localTransitOrder.getNeedUploadReceipt())
                ParamUtil.isNull(transitOrderNote.getNoteReceiptImg(), "运单需签收拍照，请至少提供一张装货图片");
            if (transitOrderNote.getNoteReceiptImg() != null && transitOrderNote.getNoteReceiptImg().split(",").length > 6)
                throw new BusinessException("最多能上传6张图片");
            for (TransitOrderNoteDetail transitOrderNoteDetail : transitOrderNote.getTransitOrderNoteDetailList()) {
                ParamUtil.isNull(transitOrderNoteDetail.getId(), "无效货物标识");
                if (transitOrderNoteDetail.getReceiptMeasure() == null || transitOrderNoteDetail.getReceiptMeasure() <= 0) {
                    throw new BusinessException("签收输入量不能等于或低于0");
                }
            }
        }
        int waitReceiptCount = transitService.getTransitOrderNoteCount(transitOrder.getId(), TransitOrderNote.NoteStatus.waitReceipt);
        int totalReceiptCount = transitService.getTransitOrderNoteCount(transitOrder.getId(), null);
        if (waitReceiptCount + transitOrderNoteList.size() < totalReceiptCount) {
            TransitOrderNote planningNote = ArrayUtil.getBy(transitOrderNoteList, obj -> obj.getId().equals(localTransitOrder.getPlanningConsigneeNoteId()));
            if (planningNote != null)
                return jsonView(FAIL_CODE, "您本次签收列表中包含终点，但你还有中途点位未签收，请先签收途径点位！");
        }
        Boolean bool = transitService.confirmArrive(getLoginUser(), localTransitOrder, transitOrderNoteList);
        return jsonView(SUCCESS_CODE, "确认送达成功", bool ? "SUCCESS" : "GOING");
    }

    /**
     * 货主确认回执
     * 3 天
     */
    @PostMapping(value = "confirmReceipt")
    @NotNull({"transitOrderId"})
    @UserTarget({UserType.shipperUser})
    public ReturnData<Object> confirmReceipt(@Explain("运单ID") String transitOrderId) {
        TransitOrder localTransitOrder = transitService.getById(transitOrderId);
        ParamUtil.isNull(localTransitOrder, "未知的运单");
        ParamUtil.notEquals("无权操作", getLoginUser().getId(), localTransitOrder.getShipperAccountId());
        ParamUtil.equals("运单锁定中,请等待处理完成", localTransitOrder.getLockingStatus(), TransitOrder.LockingStatus.locking);
        ParamUtil.notEquals("状态无法签收", localTransitOrder.getTransitStatus(), TransitOrder.TransitStatus.waitingReceipt);
        //检查支付状态
        OrderPaymentCost paymentCost = orderPaymentCostService.generateReceiptOrderPayment(localTransitOrder);
        if (paymentCost.getPayStatus() == OrderPaymentCost.PayStatus.create) return jsonErrView("请先支付运单");
        if (paymentCost.getPayStatus() == OrderPaymentCost.PayStatus.wait) return jsonErrView("请等待支付结果！");
        transitService.confirmReceipt(getLoginUser(), localTransitOrder, false);
        return jsonView(true, "签收成功");
    }

    /**
     * 销单并退款
     *
     * @param cancellation 销单说明（原因）
     */
    @PostMapping(value = "dealArbitrationRefund")
    @NotNull({"transitOrderIds", "cancellation"})
    @UserTarget({UserType.platformUser})
    public ReturnData<Object> dealArbitrationRefund(@Explain("运单数组") String[] transitOrderIds, @Explain("销单原因") String cancellation) {
        int succes = 0;
        for (String transitOrderId : transitOrderIds) {
            TransitOrder transitOrder = transitService.getById(transitOrderId);
            if (transitOrder == null) continue;
            ParamUtil.equals("运单：" + transitOrder.getTransportNo() + "已完成", transitOrder.getTransitStatus(), TransitOrder.TransitStatus.complete);
            ParamUtil.equals("运单：" + transitOrder.getTransportNo() + "已销单", transitOrder.getTransitStatus(), TransitOrder.TransitStatus.scraped);
            ParamUtil.equals("运单：" + transitOrder.getTransportNo() + "等待结算不能销单", transitOrder.getTransitStatus(), TransitOrder.TransitStatus.waitingSettlement);
            transitService.dealArbitrationRefund(getLoginUser(), transitOrder, cancellation);
            succes++;
        }
        return jsonView(true, "成功：" + succes + "条,失败：" + (transitOrderIds.length - succes) + "条");
    }

    /**
     * 获取运单车辆使用记录
     */
    @PostMapping(value = "getTransitVehicleRecordList")
    public ReturnData<List<TransitOrderVehicleRecord>> getTransitVehicleRecordList(String transitOrderId) {
        List<TransitOrderVehicleRecord> transitVehicleRecordList = transitService.getTransitVehicleRecordList(transitOrderId);
        return jsonView(true, "获取运单车辆使用记录成功", transitVehicleRecordList);
    }

    /**
     * 获取订单操作日志
     */
    @PostMapping(value = "getOrderLogList")
    public ReturnData<List<OrderAutLog>> getOrderLogList(String robOrderId, String transitOrderId) {
        if (StringUtil.isEmpty(robOrderId) && StringUtil.isEmpty(transitOrderId)) {
            return jsonView(false, "订单Id为空");
        }
        QueryWrapper<OrderAutLog> queryWrapper = new QueryWrapper<>();
        if (StringUtil.isNotEmpty(robOrderId)) {
            RobOrder localRobOrder = robService.getById(robOrderId);
            ParamUtil.isNull(localRobOrder, "未查询到订单信息");
            queryWrapper.eq("rob_order_id", robOrderId);
        } else if (StringUtil.isNotEmpty(transitOrderId)) {
            TransitOrder localTransitOrder = transitService.getById(transitOrderId);
            ParamUtil.isNull(localTransitOrder, "未查询到订单信息");
            queryWrapper.eq("transit_order_id", transitOrderId);
        }
        queryWrapper.orderByDesc("create_time");
        List<OrderAutLog> list = orderAutLogService.list(queryWrapper);
        return jsonView(true, "获取操作日志成功", list);
    }

    /**
     * 更新运单开票状态
     * 【货主发票】
     */
    @PostMapping(value = "updateOrderInvoice")
    @NotNull({"transitOrderId", "alreadyInvoice"})
    public ReturnData<Object> updateOrderInvoice(@Explain("运单ID") String transitOrderId, @Explain("开票状态") Boolean alreadyInvoice) {
        TransitOrder transitOrder = transitService.getById(transitOrderId);
        ParamUtil.notEquals("运单状态无法开发票", transitOrder.getTransitStatus(), TransitOrder.TransitStatus.complete);
        transitOrder.setAlreadyInvoice(alreadyInvoice);
        transitOrder.setUpdateUserId(getLoginUser().getId());
        transitOrder.setUpdateTime(new Date());
        transitService.updateById(transitOrder);
        return jsonView(true, "更新成功");
    }


    /**
     * 获取多运单涉及节点
     * 【司机票单专用】
     */
    @PostMapping(value = "getTransitOrderNoteListByTransitOrderIds")
    @NotNull("transitOrderIds")
    public ReturnData<List<TransitOrderNote>> getTransitOrderNoteListByTransitOrderIds(@Explain("运单IDS") String[] transitOrderIds) {
        List<TransitOrderNote> transitOrderNoteList = transitService.getTransitOrderNoteListByTransitOrderIds(transitOrderIds);
        return jsonView(SUCCESS_CODE, "获取货物节点列表成功", transitOrderNoteList);
    }

    /**
     * 获取多运单涉及货物
     * 【司机票单专用】
     */
    @PostMapping(value = "getAllTransitDetailListByTransitOrderIds")
    @NotNull("transitOrderId")
    public ReturnData<List<TransitOrderNoteDetail>> getAllTransitDetailListByTransitOrderIds(@Explain("运单IDS") String[] transitOrderIds) {
        List<TransitOrderNoteDetail> transitOrderNoteDetailList = transitService.getAllTransitDetailListByTransitOrderIds(transitOrderIds);
        return jsonView(SUCCESS_CODE, "获取货物节点列表成功", transitOrderNoteDetailList);
    }

    /**
     * 批量变更票单资料创建状态
     * 【司机票单专用】
     */
    @PostMapping(value = "updateTransitOrdersBillStatus")
    @NotNull({"transitOrderIds", "status"})
    public ReturnData<List<TransitOrderNoteDetail>> updateTransitOrdersBillStatus(@Explain("运单IDS") String[] transitOrderIds, @Explain("状态") Boolean status) {
        transitService.updateTransitOrdersBillStatus(transitOrderIds, status);
        return jsonView(SUCCESS_CODE, "更新成功");
    }

    /**
     * 根据车主+时间 获取未出票运单
     * 【司机票单专用】
     */
    @PostMapping(value = "getBillTransitOrderList")
    public ReturnData<List<TransitOrder>> getBillTransitOrderList(String robOrganizeId, String timeRange) {
        List<TransitOrder> detailList = transitService.getBillTransitOrderList(getLoginUser(), robOrganizeId, timeRange);
        return jsonView(SUCCESS_CODE, "获取成功", detailList);
    }


}
